#ifndef _GAMEOBJECT_H
#define _GAMEOBJECT_H
#include "..\BaseGameComponent.h"
#include "..\..\EdgeMath\Vectors.h"
#include "..\..\EdgeGraphics\ConstantBuffer.h"
#include "..\Delegate.h"
#include <vector>
#include "../ObjectID.h"
using namespace std;

class Model;
struct IBoundingShape;

typedef void(*collision_event_handler)(void**);

class GameObject : public BaseGameComponent
{
protected:
	// the current position of the object
	Vector3 position;
	// the current velocity of the object
	Vector3 velocity;
	// the current acceleration of the object
	Vector3 acceleration;

	// the total number of forces acting on this object
	vector<Vector3> total_forces;

	// the mass of this object
	float mass = 1.f;

	// the objects model
	Model* model;
	
	// structure for world matrix
	struct VRAM_WORLD
	{
		Matrix world;
	};
	
	// constant buffer with world view projection information
	ConstantBuffer<VRAM_WORLD>* world_buffer = nullptr;

	// get the matrix that should be sent to the graphics device
	// to transform this object when rendering
	virtual Matrix getWorldTransform(void) { return VectorHelper::Matricies::CreateScale(scale) * VectorHelper::Matricies::CreateTranslation(position); }

	// value that indicates the object will use lighting
	bool use_lighting = true;

	// object to use in collision with other objects
	// params: (this, the object being collided with)
	IBoundingShape* collider = nullptr;

	// the scale of the object
	float scale = 1.f;
public:
	// event raised when colliding with another object
	Delegate<collision_event_handler> OnCollision;

	GameObject(void);
	virtual ~GameObject(void);

	/////////////////////<Abstract functions>//////////////////////////////////////////

	virtual void Update(float dt) override;

	virtual void Draw(void) override;

	/////////////////////<Accessors>//////////////////////////////////////////

	virtual Vector3 getPosition(void) const { return position; }

	virtual Vector3 getVelocity(void) const { return velocity; }

	virtual Vector3 getAcceleration(void) const { return acceleration; }

	virtual Model* getModel(void) const { return model; }

	virtual IBoundingShape* getCollider(void) const { return collider; }

	virtual ObjectID getID(void) const = 0;

	float getScale(void) const { return scale; }

	/////////////////////<Mutators>//////////////////////////////////////////

	virtual bool getUseLighting(void) const { return use_lighting; }

	virtual void setPosition(Vector3& value) { position = value; }

	virtual void setVelocity(Vector3& value) { velocity = value; }

	virtual void setAcceleration(Vector3& value) { acceleration = value; }

	virtual void ApplyForce(Vector3& force) { total_forces.push_back(force); }

	virtual void setScale(float value) { scale = value; }

};
#endif